home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / bash / bash_108 / bash-108.zoo / src / variables.c.orig < prev    next >
Encoding:
Text File  |  1991-09-12  |  37.5 KB  |  1,582 lines

  1. /* variables.c -- Functions for hacking shell variables. */
  2.  
  3. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  4.  
  5.    This file is part of GNU Bash, the Bourne Again SHell.
  6.  
  7.    Bash is free software; you can redistribute it and/or modify it
  8.    under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 1, or (at your option)
  10.    any later version.
  11.  
  12.    Bash is distributed in the hope that it will be useful, but WITHOUT
  13.    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  14.    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
  15.    License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with Bash; see the file COPYING.  If not, write to the Free
  19.    Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <pwd.h>
  24. #include <sys/types.h>
  25.  
  26. #include "shell.h"
  27. #include "hash.h"
  28. #include "flags.h"
  29.  
  30. #if defined (USG) && !defined (isc386)
  31. struct passwd *getpwuid (), *getpwent ();
  32. #endif
  33.  
  34. /* The list of shell variables that the user has created, or that came from
  35.    the environment. */
  36. HASH_TABLE *shell_variables = (HASH_TABLE *)NULL;
  37.  
  38. /* The list of shell functions that the user has created, or that came from
  39.    the environment. */
  40. HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
  41.  
  42. /* The current variable context.  This is really a count of how deep into
  43.    executing functions we are. */
  44. int variable_context = 0;
  45.  
  46. /* The array of shell assignments which are made only in the environment
  47.    for a single command. */
  48. char **temporary_env = (char **)NULL;
  49.  
  50. /* Some funky variables which are known about specially.  Here is where
  51.    "$*", "$1", and all the cruft is kept. */
  52. char *dollar_vars[10];
  53. WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
  54.  
  55. /* The value of $$. */
  56. int dollar_dollar_pid;
  57.  
  58. /* An array which is passed to commands as their environment.  It is
  59.    manufactured from the overlap of the initial environment and the
  60.    shell variables that are marked for export. */
  61. char **export_env = (char **)NULL;
  62.  
  63. /* Non-zero means that we have to remake EXPORT_ENV. */
  64. int array_needs_making = 1;
  65.  
  66. /* The list of variables that may not be unset in this shell. */
  67. char **non_unsettable_vars = (char **)NULL;
  68.  
  69. #if defined (USG)
  70. #define DEFAULT_MAIL_PATH "/usr/mail/"
  71. #else
  72. #define DEFAULT_MAIL_PATH "/usr/spool/mail/"
  73. #endif
  74.  
  75. /* Some forward declarations. */
  76. SHELL_VAR *set_if_not ();    /* returns new or existing entry */
  77. int set_auto_export ();        /* sets for SHELL_VAR *, not for a name */
  78.  
  79. static void sbrand ();        /* set bash random number generator */
  80.  
  81. /* Initialize the shell variables from the current environment. */
  82. initialize_shell_variables (env)
  83.      char *env[];
  84. {
  85.   extern char *primary_prompt, *secondary_prompt;
  86.   char *name, *string;
  87.   int c, char_index;
  88.   int string_index = 0;
  89.   SHELL_VAR *temp_var;
  90.  
  91.   if (!shell_variables)
  92.     shell_variables = make_hash_table (0);
  93.  
  94.   if (!shell_functions)
  95.     shell_functions = make_hash_table (0);
  96.  
  97.   while (string = env[string_index++])
  98.     {
  99.       char_index = 0;
  100.  
  101.       name = (char *)alloca (1 + strlen (string));
  102.  
  103.       while ((c = *string++) && c != '=')
  104.     name[char_index++] = c;
  105.  
  106.       name[char_index] = '\0';
  107.  
  108.       /* If exported function, define it now. */
  109.       /* Posix.2 style exported function: name()=value */
  110.       if (strncmp ("() {", string, 4) == 0 ||
  111.       ((name[char_index - 1] == ')' &&
  112.         name[char_index - 2] == '(' &&
  113.         string[0] == '{')))
  114.     {
  115.       char *eval_string;
  116.  
  117.       eval_string = (char *)xmalloc (3 + strlen (string) + strlen (name));
  118.       sprintf (eval_string, "%s %s", name, string);
  119.       parse_and_execute (eval_string, name);
  120.  
  121.       if (name[char_index - 1] == ')')
  122.         name[char_index - 2] = '\0';
  123.       set_func_auto_export (name);
  124.     }
  125.       else
  126.     {
  127.       SHELL_VAR *v;
  128.  
  129.       v = bind_variable (name, string);
  130.       set_auto_export (v);
  131.     }
  132.     }
  133.  
  134.   /* Remember this pid. */
  135.   dollar_dollar_pid = getpid ();
  136.  
  137.   /* Now make our own defaults in case the vars that we think are
  138.      important are missing. */
  139.   temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
  140.   set_auto_export (temp_var);
  141.  
  142.   temp_var = set_if_not ("TERM", "dumb");
  143.   set_auto_export (temp_var);
  144.  
  145.   set_if_not ("PS1", primary_prompt);
  146.   set_if_not ("PS2", secondary_prompt);
  147.   set_if_not ("IFS", " \t\n");
  148.  
  149.   /* Magic machine types.  Pretty convenient. */
  150.   temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
  151.   set_auto_export (temp_var);
  152.  
  153.   /* Default MAILPATH, and MAILCHECK. */
  154.   set_if_not ("MAILCHECK", "60");
  155.   if ((get_string_value ("MAIL") == (char *)NULL) &&
  156.       (get_string_value ("MAILPATH") == (char *)NULL))
  157.     {
  158.       extern char *current_user_name;
  159.       char *tem;
  160.  
  161.       tem = (char *)xmalloc (1 + sizeof (DEFAULT_MAIL_PATH)
  162.                + strlen (current_user_name));
  163.       strcpy (tem, DEFAULT_MAIL_PATH);
  164.       strcat (tem, current_user_name);
  165.  
  166.       bind_variable ("MAILPATH", tem);
  167.       free (tem);
  168.     }
  169.  
  170.   /* Set up $PWD. */
  171.   {
  172.     char *get_working_directory (), *cd;
  173.  
  174.     cd = get_working_directory ("shell-init");
  175.     if (cd)
  176.       {
  177.     bind_variable ("PWD", cd);
  178.     free (cd);
  179.       }
  180.   }
  181.  
  182.   /* Do some things with shell level. */
  183.   temp_var = set_if_not ("SHLVL", "0");
  184.   set_auto_export (temp_var);
  185.   adjust_shell_level (1);
  186.  
  187.   /* Make a variable $PPID, which holds the pid of the shell's parent.  */
  188.   {
  189.     char *ppid;
  190.     SHELL_VAR *v;
  191.     extern char *itos ();
  192.  
  193.     ppid = itos ((int) getppid ());
  194.     v = find_variable ("PPID");
  195.  
  196.     if (v)
  197.       v->attributes &= ~att_readonly;
  198.  
  199.     v = bind_variable ("PPID", ppid);
  200.     v->attributes |= (att_readonly | att_integer);
  201.  
  202.     non_unsettable ("PPID");
  203.     free (ppid);
  204.   }
  205.  
  206.   /* Initialize the `getopts' stuff. */
  207.   bind_variable ("OPTIND", "1");
  208.   bind_variable ("OPTERR", "1");
  209.  
  210.   /* Get the full pathname to THIS shell, and set the BASH variable
  211.      to it. */
  212.   {
  213.     extern char *shell_name, *find_user_command (), *full_pathname ();
  214.     extern int login_shell;
  215.     char *tname = find_user_command (shell_name);
  216.  
  217.     if ((login_shell == 1) && (*shell_name != '/'))
  218.       {
  219.     struct passwd *entry = getpwuid (getuid ());
  220.  
  221.     if (entry)
  222.       {
  223.         /* If HOME doesn't exist, set it. */
  224.         temp_var = (SHELL_VAR *)find_variable ("HOME");
  225.         if (!temp_var)
  226.           {
  227.         temp_var = bind_variable ("HOME", entry->pw_dir);
  228.         temp_var->attributes |= att_exported;
  229.           }
  230.         name = savestring (entry->pw_shell);
  231.       }
  232.     else
  233.       name = savestring ("a.out");
  234.     endpwent ();
  235.       }
  236.     else
  237.       {
  238.     if (!tname)
  239.       {
  240.         char *make_absolute ();
  241.         name = make_absolute (shell_name, get_string_value ("PWD"));
  242.       }
  243.     else
  244.       {
  245.         name = full_pathname (tname);
  246.         free (tname);
  247.       }
  248.       }
  249.  
  250.     /* Make the exported environment variable SHELL be whatever the name of
  251.        this shell is.  Note that the `tset' command looks at this variable
  252.        to determine what style of commands to output; if it ends in "csh",
  253.        then C-shell commands are output, else Bourne shell commands. */
  254.     temp_var = set_if_not ("SHELL", name);
  255.     set_auto_export (temp_var);
  256.  
  257.     /* Make a variable called BASH, which is the name of THIS shell. */
  258.     temp_var = bind_variable ("BASH", name);
  259.     temp_var->attributes |= att_exported;
  260.  
  261.     free (name);
  262.   }
  263.  
  264.   /* Make a variable called BASH_VERSION which contains the version info. */
  265.   {
  266.     char tt[12];
  267.     extern char *dist_version;
  268.     extern int build_version;
  269.  
  270.     sprintf (tt, "%s.%d", dist_version, build_version);
  271.     bind_variable ("BASH_VERSION", tt);
  272.   }
  273.  
  274.   /* Set history variables to defaults, and then do whatever we would
  275.      do if the variable had just been set. */
  276.   {
  277.     char *tilde_expand ();
  278.     char *tem = tilde_expand ("~/.bash_history");
  279.  
  280.     set_if_not ("HISTFILE", tem);
  281.     free (tem);
  282.  
  283.     set_if_not ("HISTSIZE", "500");
  284.     sv_histsize ("HISTSIZE");
  285.   }
  286.  
  287.   /* seed the random number generator */
  288.  
  289.   sbrand (dollar_dollar_pid);
  290.  
  291.   /* If we have inherited `noclobber' from a previous shell, then set
  292.      noclobbering on. */
  293.   {
  294.     extern int noclobber;
  295.  
  296.     noclobber = find_variable ("noclobber") != NULL;
  297.   }
  298.  
  299.   /* Initialize the dynamic variables, and seed their values */
  300.   initialize_dynamic_variables ();
  301.  
  302.   non_unsettable ("PATH");
  303.   non_unsettable ("PS1");
  304.   non_unsettable ("PS2");
  305.   non_unsettable ("IFS");
  306.  
  307.   /* Get the users real user id, and save that in an readonly variable.
  308.      To make the variable *really* readonly, we have added it to a special
  309.      list of vars. */
  310.  
  311.   sv_uids ();
  312.   set_var_read_only ("UID");
  313.   set_var_read_only ("EUID");
  314.  
  315.   non_unsettable ("EUID");
  316.   non_unsettable ("UID");
  317. }
  318.  
  319. adjust_shell_level (change)
  320.      int change;
  321. {
  322.   extern int shell_level;
  323.   extern char *itos ();
  324.   char *new_level;
  325.   int old_level;
  326.  
  327.  
  328.   old_level = atoi (get_string_value ("SHLVL"));
  329.   shell_level = old_level + change;
  330.   new_level = itos (shell_level);
  331.   bind_variable ("SHLVL", new_level);
  332.   free (new_level);
  333. }
  334.  
  335. /* Add NAME to the list of variables that cannot be unset
  336.    if it isn't already there. */
  337. non_unsettable (name)
  338.      char *name;
  339. {
  340.   register int i;
  341.  
  342.   if (!non_unsettable_vars)
  343.     {
  344.       non_unsettable_vars = (char **)xmalloc (1 * sizeof (char *));
  345.       non_unsettable_vars[0] = (char *)NULL;
  346.     }
  347.  
  348.   for (i = 0; non_unsettable_vars[i]; i++)
  349.     if (strcmp (non_unsettable_vars[i], name) == 0)
  350.       return;
  351.  
  352.   non_unsettable_vars = (char **)
  353.     xrealloc (non_unsettable_vars, (2 + i) * sizeof (char *));
  354.   non_unsettable_vars[i] = savestring (name);
  355.   non_unsettable_vars[i + 1] = (char *)NULL;
  356. }
  357.  
  358. /* Set NAME to VALUE if NAME has no value. */
  359. SHELL_VAR *
  360. set_if_not (name, value)
  361.      char *name, *value;
  362. {
  363.   SHELL_VAR *v = find_variable (name);
  364.  
  365.   if (!v)
  366.     v = bind_variable (name, value);
  367.   return (v);
  368. }
  369.  
  370. /* Map FUNCTION over the variables in VARIABLES.  Return an array of the
  371.    variables that satisfy FUNCTION.  Satisfy means that FUNCTION returns
  372.    a non-zero value for.  A NULL value for FUNCTION means to use all
  373.    variables. */
  374. SHELL_VAR **
  375. map_over (function, var_hash_table)
  376.      Function *function;
  377.      HASH_TABLE* var_hash_table;
  378. {
  379.   register int i;
  380.   register BUCKET_CONTENTS *tlist;
  381.   SHELL_VAR *var, **list = (SHELL_VAR **)NULL;
  382.   int list_index = 0, list_size = 0;
  383.  
  384.   for (i = 0; i < var_hash_table->nbuckets; i++)
  385.     {
  386.       tlist = get_hash_bucket (i, var_hash_table);
  387.  
  388.       while (tlist)
  389.     {
  390.       var = (SHELL_VAR *)tlist->data;
  391.  
  392.       if (!function || (*function) (var))
  393.         {
  394.           if (list_index + 1 >= list_size)
  395.         list = (SHELL_VAR **)
  396.           xrealloc (list, (list_size += 20) * sizeof (SHELL_VAR *));
  397.  
  398.           list[list_index++] = var;
  399.           list[list_index] = (SHELL_VAR *)NULL;
  400.         }
  401.       tlist = tlist->next;
  402.     }
  403.     }
  404.   return (list);
  405. }
  406.  
  407. int
  408. qsort_var_comp (var1, var2)
  409.      SHELL_VAR **var1, **var2;
  410. {
  411.   return (strcmp ((*var1)->name, (*var2)->name));
  412. }
  413.  
  414. sort_variables (array)
  415.      SHELL_VAR **array;
  416. {
  417.   qsort (array, array_len (array), sizeof (SHELL_VAR *), qsort_var_comp);
  418. }
  419.  
  420. /* Create a NULL terminated array of all the shell variables in TABLE. */
  421. static SHELL_VAR **
  422. all_vars (table)
  423.      HASH_TABLE *table;
  424. {
  425.   SHELL_VAR **list;
  426.  
  427.   list = map_over ((Function *)NULL, table);
  428.   if (list)
  429.     sort_variables (list);
  430.   return (list);
  431. }
  432.  
  433. /* Create a NULL terminated array of all the shell variables. */
  434. SHELL_VAR **
  435. all_shell_variables ()
  436. {
  437.   return (all_vars (shell_variables));
  438. }
  439.  
  440. /* Create a NULL terminated array of all the shell functions. */
  441. SHELL_VAR **
  442. all_shell_functions ()
  443. {
  444.   return (all_vars (shell_functions));
  445. }
  446.  
  447. /* Print VARS to stdout in such a way that they can be read back in. */
  448. print_var_list (list)
  449.      register SHELL_VAR **list;
  450. {
  451.   register int i;
  452.   register SHELL_VAR *var;
  453.  
  454.   for (i = 0; list && (var = list[i]); i++)
  455.     if (!invisible_p (var))
  456.       print_assignment (var);
  457. }
  458.  
  459. #if defined (NOTDEF)
  460. /* Print LIST (a linked list of shell variables) to stdout
  461.    by printing the names, without the values.  Used to support the
  462.    `set +' command. */
  463. print_vars_no_values (list)
  464.      register SHELL_VAR **list;
  465. {
  466.   register int i;
  467.   register SHELL_VAR *var;
  468.  
  469.   for (i = 0; list && (var = list[i]); i++)
  470.     if (!invisible_p (var))
  471.       printf ("%s\n", var->name);
  472. }
  473. #endif
  474.  
  475. /* Print the value of a single SHELL_VAR.  No newline is
  476.    output, but the variable is printed in such a way that
  477.    it can be read back in. */
  478. print_assignment (var)
  479.      SHELL_VAR *var;
  480. {
  481.   if (function_p (var) && var->value)
  482.     {
  483.       printf ("%s=", var->name);
  484.       print_var_function (var);
  485.       printf ("\n");
  486.     }
  487.   else if (var->value)
  488.     {
  489.       printf ("%s=", var->name);
  490.       print_var_value (var);
  491.       printf ("\n");
  492.     }
  493. }
  494.  
  495. /* Print the value cell of VAR, a shell variable.  Do not print
  496.    the name, nor leading/trailing newline. */
  497. print_var_value (var)
  498.      SHELL_VAR *var;
  499. {
  500.   if (var->value)
  501.     printf ("%s", var->value);
  502. }
  503.  
  504. /* Print the function cell of VAR, a shell variable.  Do not
  505.    print the name, nor leading/trailing newline. */
  506. print_var_function (var)
  507.      SHELL_VAR *var;
  508. {
  509.   char *named_function_string ();
  510.  
  511.   if (function_p (var) && var->value)
  512.     printf ("%s", named_function_string ((char *)NULL, var->value, 1));
  513. }
  514.  
  515.  
  516. /* **************************************************************** */
  517. /*                                                                  */
  518. /*                 Dynamic Variable Extension                       */
  519. /*                                                                  */
  520. /* **************************************************************** */
  521.  
  522. /* DYNAMIC VARIABLES
  523.    
  524.    These are variables whose values are generated anew each time they are
  525.    referenced.  These are implemented using a pair of function pointers
  526.    in the struct variable: assign_func, which is called from bind_variable,
  527.    and dynamic_value, which is called from find_variable.
  528.    
  529.    assign_func is called from bind_variable, if bind_variable discovers
  530.    that the variable being assigned to has such a function.  The function
  531.    is called as
  532.       SHELL_VAR *temp = (*(entry->assign_func)) (entry, value)
  533.    and the (SHELL_VAR *)temp is returned as the value of bind_variable.  It
  534.    is usually ENTRY (self).
  535.    
  536.    dynamic_value is called from find_variable to return a `new' value for
  537.    the specified dynamic varible.  If this function is NULL, the variable
  538.    is treated as a `normal' shell variable.  If it is not, however, then
  539.    this function is called like this:
  540.       tempvar = (*(var->dynamic_value)) (var);
  541.    
  542.    Sometimes `tempvar' will replace the value of `var'.  Other times, the
  543.    shell will simply use the string value.  Pretty object-oriented, huh?
  544.    
  545.    Be warned, though: if you `unset' a special variable, it loses its
  546.    special meaning, even if you subsequently set it.
  547.    
  548.    The special assignment code would probably have been better put in
  549.    subst.c: do_assignment, in the same style as
  550.    stupidly_hack_special_variables, but I wanted the changes as
  551.    localized as possible.  */
  552.  
  553. /* The value of $SECONDS.  This is the number of seconds since shell
  554.    invocation, or, the number of seconds since the last assignment + the
  555.    value of the last assignment. */
  556. static long seconds_value_assigned = (long)0;
  557.  
  558. /* Originally defined in shell.c */
  559. extern time_t shell_start_time;
  560.  
  561. SHELL_VAR *
  562. assign_seconds (self, value)
  563.      SHELL_VAR *self;
  564.      char *value;
  565. {
  566.   seconds_value_assigned = atol (value);
  567.   shell_start_time = NOW;
  568.   return (self);
  569. }
  570.  
  571. SHELL_VAR *
  572. get_seconds (var)
  573.      SHELL_VAR *var;
  574. {
  575.   extern char *itos ();
  576.   time_t time_since_start;
  577.   char *p;
  578.  
  579.   time_since_start = NOW - shell_start_time;
  580.   p = itos((int) seconds_value_assigned + time_since_start);
  581.  
  582.   if (var->value)
  583.     free (var->value);
  584.  
  585.   var->attributes |= att_integer;
  586.   var->value = p;
  587.   return (var);
  588. }
  589.  
  590. /* The random number seed.  You can change this by setting RANDOM. */
  591. static unsigned long rseed = 1;
  592.  
  593. /* A linear congruential random number generator based on the ANSI
  594.    C standard.  A more complicated one is overkill.  */
  595.  
  596. /* Returns a pseudo-random number between 0 and 32767. */
  597. static int
  598. brand ()
  599. {
  600.   rseed = rseed * 1103515245 + 12345;
  601.   return ((unsigned int)(rseed / 65536) % 32768);
  602. }
  603.  
  604. /* Set the random number generator seed to SEED. */
  605. static void
  606. sbrand (seed)
  607.      int seed;
  608. {
  609.   rseed = seed;
  610. }
  611.  
  612. static SHELL_VAR *
  613. assign_random (self, value)
  614.      SHELL_VAR *self;
  615.      char *value;
  616. {
  617.   int s = atoi (value);
  618.  
  619.   sbrand (s);
  620.   return (self);
  621. }
  622.  
  623. static SHELL_VAR *
  624. get_random (var)
  625.      SHELL_VAR *var;
  626. {
  627.   int brand (), rv;
  628.   char *p;
  629.   extern char *itos ();
  630.  
  631.   rv = brand ();
  632.   p = itos ((int)rv);
  633.   if (var->value)
  634.     free (var->value);
  635.  
  636.   var->attributes |= att_integer;
  637.   var->value = p;
  638.   return (var);
  639. }
  640.  
  641. /* Function which returns the current line number. */
  642. static SHELL_VAR *
  643. get_lineno (var)
  644.      SHELL_VAR *var;
  645. {
  646.   extern int line_number;
  647.   char *p;
  648.   extern char *itos ();
  649.  
  650.   p = itos (line_number);
  651.   if (var->value)
  652.     free (var->value);
  653.   var->value = p;
  654.   return (var);
  655. }
  656.  
  657. initialize_dynamic_variables ()
  658. {
  659.   SHELL_VAR *v;
  660.  
  661.   v = bind_variable ("SECONDS", (char *)NULL);
  662.   v->dynamic_value = get_seconds;
  663.   v->assign_func = assign_seconds;
  664.  
  665.   v = bind_variable ("RANDOM", (char *)NULL);
  666.   v->dynamic_value = get_random;
  667.   v->assign_func = assign_random;
  668.  
  669.   v = bind_variable ("LINENO", (char *)NULL);
  670.   v->dynamic_value = get_lineno;
  671.   v->assign_func = (DYNAMIC_FUNC *)NULL;
  672. }
  673.  
  674. /* How to get a pointer to the shell variable or function named NAME.
  675.    HASHED_VARS is a pointer to the hash table containing the list
  676.    of interest (either variables or functions). */
  677. SHELL_VAR *
  678. var_lookup (name, hashed_vars)
  679.      char *name;
  680.      HASH_TABLE *hashed_vars;
  681. {
  682.   BUCKET_CONTENTS *bucket;
  683.  
  684.   bucket = find_hash_item (name, hashed_vars);
  685.  
  686.   if (bucket)
  687.     return ((SHELL_VAR *)bucket->data);
  688.   else
  689.     return ((SHELL_VAR *)NULL);
  690. }
  691.  
  692. /* Look up the variable entry whose name matches STRING.
  693.    Returns the entry or NULL. */
  694. SHELL_VAR *
  695. find_variable (name)
  696.      char *name;
  697. {
  698.   SHELL_VAR *var = var_lookup (name, shell_variables);
  699.  
  700.   if (!var)
  701.     return ((SHELL_VAR *)NULL);
  702.   else if (var->dynamic_value)
  703.     return ((*(var->dynamic_value)) (var));
  704.   else
  705.     return (var);
  706. }
  707.  
  708. /* Look up the function entry whose name matches STRING.
  709.    Returns the entry or NULL. */
  710. SHELL_VAR *
  711. find_function (name)
  712.      char *name;
  713. {
  714.   return (var_lookup (name, shell_functions));
  715. }
  716.  
  717. /* Return the string value of a variable.  Return NULL if the variable
  718.    doesn't exist, or only has a function as a value.  Don't cons a new
  719.    string. */
  720. char *
  721. get_string_value (var_name)
  722.      char *var_name;
  723. {
  724.   SHELL_VAR *var = find_variable (var_name);
  725.  
  726.   if (!var)
  727.     return (char *)NULL;
  728.   else
  729.     return (var->value);
  730. }
  731.  
  732. /* Create a local variable referenced by NAME. */
  733. SHELL_VAR *
  734. make_local_variable (name)
  735.      char *name;
  736. {
  737.   SHELL_VAR *new_var, *old_var, *bind_variable ();
  738.   BUCKET_CONTENTS *elt;
  739.  
  740.   /* local foo; local foo;  is a no-op. */
  741.   old_var = find_variable (name);
  742.   if (old_var && old_var->context == variable_context)
  743.     return (old_var);
  744.  
  745.   elt = remove_hash_item (name, shell_variables);
  746.   if (elt)
  747.     {
  748.       old_var = (SHELL_VAR *)elt->data;
  749.       free (elt->key);
  750.       free (elt);
  751.     }
  752.   else
  753.     old_var = (SHELL_VAR *)NULL;
  754.  
  755.   /* If a variable does not already exist with this name, then
  756.      just make a new one. */
  757.   if (!old_var)
  758.     {
  759.       new_var = bind_variable (name, "");
  760.     }
  761.   else
  762.     {
  763.       new_var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  764.  
  765.       new_var->name = savestring (name);
  766.       new_var->value = savestring ("");
  767.  
  768.       new_var->dynamic_value = (DYNAMIC_FUNC *)NULL;
  769.       new_var->assign_func = (DYNAMIC_FUNC *)NULL;
  770.  
  771.       new_var->attributes = 0;
  772.  
  773.       if (exported_p (old_var))
  774.     new_var->attributes |= att_exported;
  775.  
  776.       new_var->prev_context = old_var;
  777.       elt = add_hash_item (savestring (name), shell_variables);
  778.       elt->data = (char *)new_var;
  779.     }
  780.  
  781.   new_var->context = variable_context;
  782.   return (new_var);
  783. }
  784.  
  785. /* Bind a variable NAME to VALUE.  This conses up the name
  786.    and value strings. */
  787. SHELL_VAR *
  788. bind_variable (name, value)
  789.      char *name, *value;
  790. {
  791.   SHELL_VAR *entry = find_variable (name);
  792.  
  793.   if (!entry)
  794.     {
  795.       /* Make a new entry for this variable.  Then do the binding. */
  796.       entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  797.  
  798.       entry->attributes = 0;
  799.       entry->name = savestring (name);
  800.  
  801.       if (value)
  802.     entry->value = savestring (value);
  803.       else
  804.     entry->value = (char *)NULL;
  805.  
  806.       entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
  807.       entry->assign_func = (DYNAMIC_FUNC *)NULL;
  808.  
  809.       /* Always assume variables are to be made at toplevel!
  810.      make_local_variable has the responsibilty of changing the
  811.      variable context. */
  812.       entry->context = 0;
  813.       entry->prev_context = (SHELL_VAR *)NULL;
  814.  
  815.       {
  816.     BUCKET_CONTENTS *elt;
  817.  
  818.     elt = add_hash_item (savestring (name), shell_variables);
  819.     elt->data = (char *)entry;
  820.       }
  821.     }
  822.   else if (entry->assign_func)
  823.     return ((*(entry->assign_func)) (entry, value));
  824.   else
  825.     {
  826.       if (readonly_p (entry))
  827.     {
  828.       report_error ("%s: read-only variable", name);
  829.       return (entry);
  830.     }
  831.  
  832.       /* If this variable has had its type set to integer (via `declare -i'),
  833.      then do expression evaluation on it and store the result.  The
  834.      functions in expr.c (evalexp and bind_int_variable) are responsible
  835.      for turning off the integer flag if they don't want further
  836.      evaluation done. */
  837.       if (integer_p (entry))
  838.     {
  839.       long val, evalexp();
  840.       extern char *itos();
  841.  
  842.       val = evalexp (value);
  843.       /* We cannot free () entry->value before this; what if the string
  844.          we are working is `even=even+2'?  We need the original value
  845.          around while we are doing the evaluation to handle any possible
  846.          recursion. */
  847.       if (entry->value)
  848.         free (entry->value);
  849.  
  850.       entry->value = itos (val);
  851.     }
  852.       else
  853.     {
  854.       if (entry->value)
  855.         free (entry->value);
  856.  
  857.       if (value)
  858.         entry->value = savestring (value);
  859.       else
  860.         entry->value = (char *)NULL;
  861.     }
  862.     }
  863.  
  864.   if (mark_modified_vars)
  865.     entry->attributes |= att_exported;
  866.  
  867.   if (exported_p (entry))
  868.     array_needs_making = 1;
  869.  
  870.   return (entry);
  871. }
  872.  
  873. /* Dispose of the information attached to VAR. */
  874. dispose_variable (var)
  875.      SHELL_VAR *var;
  876. {
  877.   if (!var)
  878.     return;
  879.  
  880.   if (function_p (var))
  881.     dispose_command (var->value);
  882.   else if (var->value)
  883.     free (var->value);
  884.  
  885.   free (var->name);
  886.  
  887.   if (exported_p (var))
  888.     array_needs_making = 1;
  889.  
  890.   free (var);
  891. }
  892.  
  893. /* Unset the variable referenced by NAME. */
  894. unbind_variable (name)
  895.      char *name;
  896. {
  897.   SHELL_VAR *var = find_variable (name);
  898.  
  899.   if (!var)
  900.     return (-1);
  901.  
  902.   if (var->value)
  903.     {
  904.       free (var->value);
  905.       var->value = (char *)NULL;
  906.     }
  907.  
  908.   makunbound (name, shell_variables);
  909.  
  910.   return (0);
  911. }
  912.  
  913. /* Make the variable associated with NAME go away.  HASH_LIST is the
  914.    hash table from which this variable should be deleted (either
  915.    shell_variables or shell_functions).
  916.    Returns non-zero if the variable couldn't be found. */
  917. makunbound (name, hash_list)
  918.      char *name;
  919.      HASH_TABLE *hash_list;
  920. {
  921.   BUCKET_CONTENTS *elt;
  922.   SHELL_VAR *old_var, *new_var;
  923.  
  924.   elt = remove_hash_item (name, hash_list);
  925.  
  926.   if (!elt)
  927.     return (-1);
  928.  
  929.   old_var = (SHELL_VAR *)elt->data;
  930.   new_var = old_var->prev_context;
  931.  
  932.   if (old_var && exported_p (old_var))
  933.     array_needs_making++;
  934.  
  935.   if (new_var)
  936.     {
  937.       /* Has to be a variable, functions don't have previous contexts. */
  938.       BUCKET_CONTENTS *new_elt;
  939.  
  940.       new_elt = add_hash_item (savestring (new_var->name), hash_list);
  941.       new_elt->data = (char *)new_var;
  942.  
  943.       if (exported_p (new_var))
  944.     set_var_auto_export (new_var->name);
  945.     }
  946.  
  947.   free (elt->key);
  948.   free (elt);
  949.  
  950.   dispose_variable (old_var);
  951.   stupidly_hack_special_variables (name);
  952.   return (0);
  953. }
  954.  
  955. /* Remove the variable with NAME if it is a local variable in the
  956.    current context. */
  957. kill_local_variable (name)
  958.      char *name;
  959. {
  960.   SHELL_VAR *temp = find_variable (name);
  961.  
  962.   if (temp && (temp->context == variable_context))
  963.     {
  964.       makunbound (name, shell_variables);
  965.       return (0);
  966.     }
  967.   return (-1);
  968. }
  969.  
  970. /* Get rid of all of the variables in the current context. */
  971. int
  972. variable_in_context (var)
  973.      SHELL_VAR *var;
  974. {
  975.   return (var && var->context == variable_context);
  976. }
  977.  
  978. kill_all_local_variables ()
  979. {
  980.   register int i, pass;
  981.   register SHELL_VAR *var, **list;
  982.   HASH_TABLE *varlist;
  983.  
  984.   for (pass = 0; pass < 2; pass++)
  985.     {
  986.       varlist = pass ? shell_functions : shell_variables;
  987.  
  988.       list = map_over (variable_in_context, varlist);
  989.  
  990.       if (list)
  991.     {
  992.       for (i = 0; var = list[i]; i++)
  993.         makunbound (var->name, varlist);
  994.  
  995.       free (list);
  996.     }
  997.     }
  998. }
  999.  
  1000. /* Delete the entire contents of the hash table. */
  1001. delete_all_variables (hashed_vars)
  1002.      HASH_TABLE *hashed_vars;
  1003. {
  1004.   register int i;
  1005.   register BUCKET_CONTENTS *bucket;
  1006.  
  1007.   for (i = 0; i < hashed_vars->nbuckets; i++)
  1008.     {
  1009.       bucket = hashed_vars->bucket_array[i];
  1010.  
  1011.       while (bucket)
  1012.     {
  1013.       BUCKET_CONTENTS *temp = bucket;
  1014.       SHELL_VAR *var, *prev;
  1015.  
  1016.       bucket = bucket->next;
  1017.  
  1018.       var = (SHELL_VAR *)temp->data;
  1019.  
  1020.       while (var)
  1021.         {
  1022.           prev = var->prev_context;
  1023.           dispose_variable (var);
  1024.  
  1025.           var = prev;
  1026.         }
  1027.  
  1028.       free (temp->key);
  1029.       free (temp);
  1030.     }
  1031.       hashed_vars->bucket_array[i] = (BUCKET_CONTENTS *)NULL;
  1032.     }
  1033. }
  1034.  
  1035. SHELL_VAR *
  1036. new_shell_variable (name)
  1037.      char *name;
  1038. {
  1039.   SHELL_VAR *var;
  1040.  
  1041.   var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  1042.  
  1043.   bzero (var, sizeof (SHELL_VAR));
  1044.   var->name = savestring (name);
  1045.   return (var);
  1046. }
  1047.  
  1048. /* Do a function binding to a variable.  You pass the name and
  1049.    the command to bind to.  This conses the name and command. */
  1050. SHELL_VAR *
  1051. bind_function (name, value)
  1052.      char *name;
  1053.      COMMAND *value;
  1054. {
  1055.   SHELL_VAR *entry = find_function (name);
  1056.  
  1057.   if (!entry)
  1058.     {
  1059.       BUCKET_CONTENTS *elt;
  1060.  
  1061.       elt = add_hash_item (savestring (name), shell_functions);
  1062.  
  1063.       elt->data = (char *)new_shell_variable (name);
  1064.       entry = (SHELL_VAR *)elt->data;
  1065.       entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
  1066.       entry->assign_func = (DYNAMIC_FUNC *)NULL;
  1067.  
  1068.       /* Functions are always made at the top level.  This allows a
  1069.      function to define another function (like autoload). */
  1070.       entry->context = 0;
  1071.     }
  1072.  
  1073.   if (entry->value)
  1074.     dispose_command (entry->value);
  1075.  
  1076.   if (value)    /* I don't think this can happen anymore */
  1077.     entry->value = (char *)copy_command (value);
  1078.   else
  1079.     entry->value = (char *)NULL;
  1080.  
  1081.   entry->attributes |= att_function;
  1082.  
  1083.   if (mark_modified_vars)
  1084.     entry->attributes |= att_exported;
  1085.  
  1086.   entry->attributes &= ~att_invisible;    /* Just to be sure */
  1087.  
  1088.   array_needs_making = 1;
  1089.  
  1090.   return (entry);
  1091. }
  1092.  
  1093. /* Copy VAR to a new data structure and return that structure. */
  1094. SHELL_VAR *
  1095. copy_variable (var)
  1096.      SHELL_VAR *var;
  1097. {
  1098.   SHELL_VAR *copy = (SHELL_VAR *)NULL;
  1099.  
  1100.   if (var)
  1101.     {
  1102.       copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  1103.  
  1104.       copy->attributes = var->attributes;
  1105.       copy->name = savestring (var->name);
  1106.  
  1107.       if (function_p (var))
  1108.     copy->value = (char *)copy_command (var->value);
  1109.       else if (var->value)
  1110.     copy->value = savestring (var->value);
  1111.       else
  1112.     copy->value = (char *)NULL;
  1113.  
  1114.       copy->dynamic_value = var->dynamic_value;
  1115.       copy->assign_func = var->assign_func;
  1116.  
  1117.       copy->context = var->context;
  1118.  
  1119.       /* Don't bother copying previous contexts along with this variable. */
  1120.       copy->prev_context = (SHELL_VAR *)NULL;
  1121.     }
  1122.   return (copy);
  1123. }
  1124.  
  1125. /* Make the variable associated with NAME be read-only.
  1126.    If NAME does not exist yet, create it. */
  1127. set_var_read_only (name)
  1128.      char *name;
  1129. {
  1130.   SHELL_VAR *entry = find_variable (name);
  1131.  
  1132.   if (!entry)
  1133.     {
  1134.       entry = bind_variable (name, "");
  1135.       if (!no_invisible_vars)
  1136.     entry->attributes |= att_invisible;
  1137.     }
  1138.   entry->attributes |= att_readonly;
  1139. }
  1140.  
  1141. /* Make the function associated with NAME be read-only.
  1142.    If NAME does not exist, we just punt, like auto_export code below. */
  1143. set_func_read_only (name)
  1144.      char *name;
  1145. {
  1146.   SHELL_VAR *entry = find_function (name);
  1147.  
  1148.   if (entry)
  1149.     entry->attributes |= att_readonly;
  1150. }
  1151.  
  1152. /* Make VAR be auto-exported.  This is used when a lookup has just
  1153.    been performed, so another one is not needed. */
  1154. set_auto_export (var)
  1155.   SHELL_VAR *var;
  1156. {
  1157.   var->attributes |= att_exported;
  1158.   array_needs_making = 1;
  1159. }
  1160.  
  1161. /* Make the variable associated with NAME be auto-exported.
  1162.    If NAME does not exist yet, create it. */
  1163. set_var_auto_export (name)
  1164.      char *name;
  1165. {
  1166.   SHELL_VAR *entry = find_variable (name);
  1167.  
  1168.   if (!entry)
  1169.     {
  1170.       entry = bind_variable (name, "");
  1171.       if (!no_invisible_vars)
  1172.     entry->attributes |= att_invisible;
  1173.     }
  1174.   entry->attributes |= att_exported;
  1175.   array_needs_making = 1;
  1176. }
  1177.  
  1178. /* Make the function associated with NAME be auto-exported. */
  1179. set_func_auto_export (name)
  1180.      char *name;
  1181. {
  1182.   SHELL_VAR *entry = find_function (name);
  1183.  
  1184.   if (entry)
  1185.     {
  1186.       entry->attributes |= att_exported;
  1187.       array_needs_making = 1;
  1188.     }
  1189. }
  1190.  
  1191. /* Returns non-zero if STRING is an assignment statement.  The returned value
  1192.    is the index of the `=' sign. */
  1193. assignment (string)
  1194.      char *string;
  1195. {
  1196.   register int c, index = 0;
  1197.  
  1198.   c = string[index];
  1199.   if (!isletter (c) && c != '_')
  1200.     return (0);
  1201.  
  1202.   while (c = string[index])
  1203.     {
  1204.       /* The following is safe.  Note that '=' at the start of a word
  1205.      is not an assignment statement. */
  1206.       if (c == '=')
  1207.     return (index);
  1208.  
  1209.       if (!isletter (c) && !digit (c) && c != '_')
  1210.     return (0);
  1211.  
  1212.       index++;
  1213.     }
  1214.   return (0);
  1215. }
  1216.  
  1217. int
  1218. visible_var (var)
  1219.      SHELL_VAR *var;
  1220. {
  1221.   return (!invisible_p (var));
  1222. }
  1223.  
  1224. SHELL_VAR **
  1225. all_visible_variables ()
  1226. {
  1227.   SHELL_VAR **list;
  1228.  
  1229.   list = map_over (visible_var, shell_variables);
  1230.   if (list)
  1231.     sort_variables (list);
  1232.   return (list);
  1233. }
  1234.  
  1235. SHELL_VAR **
  1236. all_visible_functions ()
  1237. {
  1238.   SHELL_VAR **list;
  1239.  
  1240.   list = map_over (visible_var, shell_functions);
  1241.   if (list)
  1242.     sort_variables (list);
  1243.   return (list);
  1244. }
  1245.  
  1246. /* Return non-zero if the variable VAR is visible and exported. */
  1247. int
  1248. visible_and_exported (var)
  1249.      SHELL_VAR *var;
  1250. {
  1251.   return (!invisible_p (var) && exported_p (var));
  1252. }
  1253.  
  1254. /* Make an array of assignment statements from the hash table
  1255.    HASHED_VARS which contains SHELL_VARs.  Only visible, exported
  1256.    variables are eligible. */
  1257. char **
  1258. make_var_array (hashed_vars)
  1259.      HASH_TABLE *hashed_vars;
  1260. {
  1261.   register int i, list_index;
  1262.   register SHELL_VAR *var;
  1263.   char **list = (char **)NULL;
  1264.   SHELL_VAR **vars;
  1265.  
  1266.   vars = map_over (visible_and_exported, hashed_vars);
  1267.  
  1268.   if (!vars)
  1269.     return (char **)NULL;
  1270.  
  1271.   list = (char **)xmalloc ((1 + array_len ((char **)vars)) * sizeof (char *));
  1272.  
  1273.   for (i = 0, list_index = 0; var = vars[i]; i++)
  1274.     {
  1275.       char *value, *named_function_string ();
  1276.  
  1277.       if (function_p (var))
  1278.     {
  1279.       value =
  1280.         named_function_string ((char *)NULL,
  1281.                    (COMMAND *)function_cell (var), 0);
  1282.     }
  1283.       else
  1284.     value = value_cell (var);
  1285.  
  1286.       if (value)
  1287.     {
  1288. #if 0
  1289.       list[list_index] =
  1290.         (char *)xmalloc (2 + strlen (var->name) + strlen (value));
  1291.  
  1292.       sprintf (list[list_index], "%s=%s", var->name, value);
  1293. #else
  1294.       /* Let's see if this makes any kind of performance difference. */
  1295.       int name_len = strlen (var->name);
  1296.       int value_len = strlen (value);
  1297.       char    *p;
  1298.  
  1299.       p = list[list_index] =  (char *)xmalloc (2 + name_len + value_len);
  1300.       strcpy (p, var->name);
  1301.       p[name_len] = '=';
  1302.       strcpy (&p[name_len + 1], value);
  1303. #endif
  1304.       list_index++;
  1305.     }
  1306.     }
  1307.  
  1308.   free (vars);
  1309.   list[list_index] = (char *)NULL;
  1310.   return (list);
  1311. }
  1312.  
  1313. /* Add STRING to the array of foo=bar strings that we already
  1314.    have to add to the environment.  */
  1315. assign_in_env (string)
  1316.      char *string;
  1317. {
  1318.   int size;
  1319.  
  1320.   int offset = assignment (string);
  1321.   char *name = savestring (string);
  1322.   char *temp, *value = (char *)NULL;
  1323.  
  1324.   if (name[offset] == '=')
  1325.     {
  1326.       char *tilde_expand (), *string_list ();
  1327.       WORD_LIST *list, *expand_string_unsplit ();
  1328.  
  1329.       name[offset] = 0;
  1330.       temp = name + offset + 1;
  1331.       temp = tilde_expand (temp);
  1332.  
  1333.       list = expand_string_unsplit (temp, 0);
  1334.       value = string_list (list);
  1335.  
  1336.       if (list)
  1337.     dispose_words (list);
  1338.  
  1339.       free (temp);
  1340.     }
  1341.  
  1342.   if (!value) value = savestring ("");
  1343.  
  1344.   temp = (char *)xmalloc (2 + strlen (name) + strlen (value));
  1345.   sprintf (temp, "%s=%s", name, value);
  1346.   free (name);
  1347.  
  1348.   if (!temporary_env)
  1349.     {
  1350.       temporary_env = (char **)xmalloc (sizeof (char *));
  1351.       temporary_env [0] = (char *)NULL;
  1352.     }
  1353.  
  1354.   size = array_len (temporary_env);
  1355.   temporary_env = (char **)
  1356.     xrealloc (temporary_env, (size + 2) * (sizeof (char *)));
  1357.  
  1358.   temporary_env[size] = (temp);
  1359.   temporary_env[size + 1] = (char *)NULL;
  1360.   array_needs_making = 1;
  1361.  
  1362.   if (echo_command_at_execute)
  1363.     {
  1364.       /* The K*rn shell prints the `+ ' in front of assignment statements,
  1365.      so we do too. */
  1366.       extern char *indirection_level_string ();
  1367.       fprintf (stderr, "%s%s\n", indirection_level_string (), temp);
  1368.       fflush (stderr);
  1369.     }
  1370. }
  1371.  
  1372. /* Find a variable in the temporary environment that is named NAME.
  1373.    Return a consed variable, or NULL if not found. */
  1374. SHELL_VAR *
  1375. find_tempenv_variable (name)
  1376.      char *name;
  1377. {
  1378.   register int i, l = strlen (name);
  1379.  
  1380.   if (!temporary_env)
  1381.     return ((SHELL_VAR *)NULL);
  1382.  
  1383.   for (i = 0; temporary_env[i]; i++)
  1384.     {
  1385.       if (strncmp (temporary_env[i], name, l) == 0 &&
  1386.       temporary_env[i][l] == '=')
  1387.     {
  1388.       SHELL_VAR *temp;
  1389.  
  1390.       temp = new_shell_variable (name);
  1391.  
  1392.       if (temporary_env[i][l + 1])
  1393.         temp->value = savestring (&temporary_env[i][l + 1]);
  1394.       else
  1395.         temp->value = savestring ("");
  1396.       temp->attributes = att_exported;
  1397.       temp->context = 0;
  1398.       temp->prev_context = (SHELL_VAR *)NULL;
  1399.  
  1400.       temp->dynamic_value = (DYNAMIC_FUNC *)NULL;
  1401.       temp->assign_func = (DYNAMIC_FUNC *)NULL;
  1402.  
  1403.       return (temp);
  1404.     }
  1405.     }
  1406.   return ((SHELL_VAR *)NULL);
  1407. }
  1408.  
  1409. /* Free the storage used in the variable array for temporary
  1410.    environment variables. */
  1411. dispose_used_env_vars ()
  1412. {
  1413.   if (!temporary_env)
  1414.     return;
  1415.  
  1416.   free_array (temporary_env);
  1417.   temporary_env = (char **)NULL;
  1418.   array_needs_making = 1;
  1419. }
  1420.  
  1421. /* Stupid comparison routine for qsort () ing strings. */
  1422. qsort_string_compare (s1, s2)
  1423.      register char **s1, **s2;
  1424. {
  1425.   return (strcmp (*s1, *s2));
  1426. }
  1427.  
  1428. #define ISFUNC(s, o) ((s[o + 1] == '(')  && (s[o + 2] == ')'))
  1429.  
  1430. /* Add ASSIGN to ARRAY, or supercede a previous assignment in the
  1431.    array with the same left-hand side.  Return the new array. */
  1432. char **
  1433. add_or_supercede (assign, array)
  1434.      char *assign;
  1435.      register char **array;
  1436. {
  1437.   register int i;
  1438.   int equal_offset = assignment (assign);
  1439.  
  1440.   if (!equal_offset)
  1441.     return (array);
  1442.  
  1443.   /* If this is a function, then only supercede the function definition.
  1444.      We do this by including the `=(' in the comparison.  */
  1445.   if (assign[equal_offset + 1] == '(')
  1446.     equal_offset++;
  1447.  
  1448.   for (i = 0; array[i]; i++)
  1449.     {
  1450.       if (STREQN (assign, array[i], equal_offset + 1))
  1451.     {
  1452.       free (array[i]);
  1453.       array[i] = savestring (assign);
  1454.       return (array);
  1455.     }
  1456.     }
  1457.   array = (char **)xrealloc (array, (2 + array_len (array)) * sizeof (char *));
  1458.   array[i++] = savestring (assign);
  1459.   array[i] = (char *)NULL;
  1460.   return (array);
  1461. }
  1462.  
  1463. /* Make the environment array for the command about to be executed.  If the
  1464.    array needs making.  Otherwise, do nothing.  If a shell action could
  1465.    change the array that commands receive for their environment, then the
  1466.    code should `array_needs_making++'. */
  1467. maybe_make_export_env ()
  1468. {
  1469.   register int i;
  1470.   register char **temp_array;
  1471.  
  1472.   if (array_needs_making)
  1473.     {
  1474.       if (export_env)
  1475.     free_array (export_env);
  1476.  
  1477. #ifdef SHADOWED_ENV
  1478.       export_env =
  1479.     (char **)xmalloc ((1 + array_len (shell_environment)) * sizeof (char *));
  1480.  
  1481.       for (i = 0; shell_environment[i]; i++)
  1482.     export_env[i] = savestring (shell_environment[i]);
  1483.       export_env[i] = (char *)NULL;
  1484.  
  1485. #else /* !SHADOWED_ENV */
  1486.  
  1487.       export_env = (char **)xmalloc (sizeof (char *));
  1488.       export_env[0] = (char *)NULL;
  1489.  
  1490. #endif /* SHADOWED_ENV */
  1491.  
  1492.       temp_array = make_var_array (shell_variables);
  1493.       for (i = 0; temp_array && temp_array[i]; i++)
  1494.     export_env = add_or_supercede (temp_array[i], export_env);
  1495.       free_array (temp_array);
  1496.  
  1497.       temp_array = make_var_array (shell_functions);
  1498.       for (i = 0; temp_array && temp_array[i]; i++)
  1499.     export_env = add_or_supercede (temp_array[i], export_env);
  1500.       free_array (temp_array);
  1501.  
  1502.       if (temporary_env)
  1503.     {
  1504.       for (i = 0; temporary_env[i]; i++)
  1505.         export_env = add_or_supercede (temporary_env[i], export_env);
  1506.  
  1507.       /* Sort the array alphabetically. */
  1508.       qsort (export_env, array_len (export_env),
  1509.          sizeof (char *), qsort_string_compare);
  1510.     }
  1511.       array_needs_making = 0;
  1512.     }
  1513. }
  1514.  
  1515. /* We always put _ in the environment as the name of this command. */
  1516. put_command_name_into_env (command_name)
  1517.      char *command_name;
  1518. {
  1519.   char *dummy;
  1520.  
  1521.   dummy = (char *)xmalloc (4 + strlen (command_name));
  1522.  
  1523.   /* These three statements replace a call to sprintf */
  1524.   dummy[0] = '_';
  1525.   dummy[1] = '=';
  1526.   strcpy (&dummy[2], command_name);
  1527.   export_env = add_or_supercede (dummy, export_env);
  1528.   free (dummy);
  1529. }
  1530.  
  1531. /* We supply our own version of getenv () because we want library
  1532.    routines to get the changed values of exported variables. */
  1533. char *last_tempenv_value = (char *)NULL;
  1534.  
  1535. /* The NeXT C library has getenv () defined and used in the same file.
  1536.    This screws our scheme.  However, Bash will run on the NeXT using
  1537.    the C library getenv (), since right now the only environment variable
  1538.    that we care about is HOME, and that is already defined.  */
  1539. #if !defined (NeXT)
  1540. char *
  1541. getenv (name)
  1542.      char *name;
  1543. {
  1544.   SHELL_VAR *var = find_tempenv_variable (name);
  1545.  
  1546.   if (var)
  1547.     {
  1548.       if (last_tempenv_value)
  1549.     free (last_tempenv_value);
  1550.  
  1551.       last_tempenv_value = savestring (value_cell (var));
  1552.       dispose_variable (var);
  1553.       return (last_tempenv_value);
  1554.     }
  1555.   else if (shell_variables)
  1556.     {
  1557.       var = find_variable (name);
  1558.       if (var && exported_p (var))
  1559.     return (value_cell (var));
  1560.     }
  1561.   else
  1562.     {
  1563.       register int i, len = strlen (name);
  1564.       extern char **environ;
  1565.  
  1566.       /* In some cases, s5r3 invokes getenv() before main(); BSD systems
  1567.          using gprof also exhibit this behavior.  This means that
  1568.          shell_variables will be 0 when this is invoked.  We look up the
  1569.      variable in the real environment in that case. */
  1570.  
  1571.       for (i = 0; environ[i]; i++)
  1572.     {
  1573.       if ((strncmp (environ[i], name, len) == 0) &&
  1574.           (environ[i][len] == '='))
  1575.         return (environ[i] + len + 1);
  1576.     }
  1577.     }
  1578.  
  1579.   return ((char *)NULL);
  1580. }
  1581. #endif /* NeXT */
  1582.